#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/spi_master.h"
#include "driver/i2c.h"
#include "esp_lcd_panel_io.h"
#include "esp_lcd_panel_vendor.h"
#include "esp_lcd_panel_ops.h"
#include "esp_lcd_panel_commands.h"
#include "esp_log.h"
#include "esp_lcd_co5300.h"

// LVGL相关头文件
#include "esp_lvgl_port.h"
#include "lvgl.h"
#include "lv_demos.h"


// 触摸相关头文件
#include "esp_lcd_touch.h"
#include "esp_lcd_touch_cst9217.h"

static const char *TAG = "AMOLED_CO5300_LVGL";

// 硬件引脚定义 - AMOLED屏幕无需背光
#define EXAMPLE_PIN_NUM_LCD_CS            (GPIO_NUM_18)
#define EXAMPLE_PIN_NUM_LCD_PCLK          (GPIO_NUM_15) 
#define EXAMPLE_PIN_NUM_LCD_DATA0         (GPIO_NUM_14)
#define EXAMPLE_PIN_NUM_LCD_DATA1         (GPIO_NUM_21)
#define EXAMPLE_PIN_NUM_LCD_DATA2         (GPIO_NUM_17)
#define EXAMPLE_PIN_NUM_LCD_DATA3         (GPIO_NUM_16)
#define EXAMPLE_PIN_NUM_LCD_RST           (GPIO_NUM_13)

// 触摸屏I2C引脚定义 - 轮询模式
#define EXAMPLE_PIN_NUM_TOUCH_SDA         (GPIO_NUM_10)
#define EXAMPLE_PIN_NUM_TOUCH_SCL         (GPIO_NUM_9)
#define EXAMPLE_PIN_NUM_TOUCH_INT         (-1)
#define EXAMPLE_PIN_NUM_TOUCH_RST         (-1)

#define EXAMPLE_LCD_H_RES              410
#define EXAMPLE_LCD_V_RES              502
#define EXAMPLE_LCD_X_GAP              22
#define EXAMPLE_LCD_Y_GAP              0
#define AMOLED_QSPI_MAX_PCLK           80 * 1000 * 1000

// LVGL配置
#define LVGL_TASK_MAX_DELAY_MS         2
#define LVGL_TASK_MIN_DELAY_MS         1
#define LVGL_TASK_STACK_SIZE           (12 * 1024)  // 增加到12KB
#define LVGL_TASK_PRIORITY             2

// 全局变量
static esp_lcd_panel_handle_t panel_handle = NULL;
static esp_lcd_panel_io_handle_t panel_io_handle = NULL;
static lv_display_t *lvgl_disp = NULL;
static esp_lcd_touch_handle_t touch_handle = NULL;
static lv_indev_t *lvgl_touch_indev = NULL;

/**
 * @brief AMOLED屏幕偶数对齐事件回调函数 - 解决屏幕撕裂问题  
 * LVGL 9.x版本使用事件系统实现rounder功能
 */
static void amoled_rounder_event_cb(lv_event_t *e)
{
    lv_event_code_t code = lv_event_get_code(e);
    
    if (code == LV_EVENT_INVALIDATE_AREA) {
        lv_area_t *area = (lv_area_t *)lv_event_get_param(e);
        if (area == NULL) return;
        
        // CO5300 AMOLED偶数对齐逻辑
        // 确保起始坐标为偶数
        if (area->x1 % 2 != 0)
            area->x1 -= 1;
        if (area->y1 % 2 != 0)
            area->y1 -= 1;

        // 确保宽度和高度为偶数
        uint32_t w = (area->x2 - area->x1 + 1);
        uint32_t h = (area->y2 - area->y1 + 1);
        if (w % 2 != 0)
            area->x2 += 1;
        if (h % 2 != 0)
            area->y2 += 1;
            
        // 确保不超出屏幕边界
        if (area->x2 >= EXAMPLE_LCD_H_RES)
            area->x2 = EXAMPLE_LCD_H_RES - 1;
        if (area->y2 >= EXAMPLE_LCD_V_RES)
            area->y2 = EXAMPLE_LCD_V_RES - 1;
    }
}

/**
 * @brief AMOLED屏幕偶数对齐优化配置
 * 通过缓冲区配置实现偶数对齐，避免屏幕撕裂
 */
static void configure_amoled_alignment(void)
{
    ESP_LOGI(TAG, "配置AMOLED屏幕偶数对齐优化");
    ESP_LOGI(TAG, "缓冲区大小已调整为偶数行: %d 像素", EXAMPLE_LCD_H_RES * 50);
    ESP_LOGI(TAG, "RGB565像素格式天然支持2字节对齐");
    ESP_LOGI(TAG, "QSPI时钟: %d MHz，优化传输效率", AMOLED_QSPI_MAX_PCLK / 1000000);
}

/**
 * @brief AMOLED屏幕自发光，无需背光初始化
 */
static void init_backlight(void)
{
    ESP_LOGI(TAG, "AMOLED屏幕自发光，无需背光配置");
}

/**
 * @brief 初始化I2C总线用于触摸屏
 */
static esp_lcd_panel_io_handle_t init_touch_i2c(void)
{
    ESP_LOGI(TAG, "初始化触摸I2C总线...");
    
    // 配置I2C总线 - 轮询模式，无中断
    i2c_config_t i2c_conf = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = EXAMPLE_PIN_NUM_TOUCH_SDA,
        .scl_io_num = EXAMPLE_PIN_NUM_TOUCH_SCL,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .master.clk_speed = 100 * 1000,  // 100KHz
    };
    
    ESP_ERROR_CHECK(i2c_param_config(I2C_NUM_0, &i2c_conf));
    ESP_ERROR_CHECK(i2c_driver_install(I2C_NUM_0, i2c_conf.mode, 0, 0, 0));
    ESP_LOGI(TAG, "I2C总线初始化成功");
    
    // 创建I2C面板IO
    esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_CST9217_CONFIG();
    esp_lcd_panel_io_handle_t tp_io_handle = NULL;
    
    ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c((esp_lcd_i2c_bus_handle_t)I2C_NUM_0, &tp_io_config, &tp_io_handle));
    ESP_LOGI(TAG, "触摸面板IO创建成功");
    
    return tp_io_handle;
}

/**
 * @brief 初始化触摸屏
 */
static void init_touch_panel(esp_lcd_panel_io_handle_t tp_io_handle)
{
    ESP_LOGI(TAG, "初始化CST9217触摸面板...");
    ESP_LOGI(TAG, "轮询模式配置: SDA=%d, SCL=%d, 地址=0x%02X", 
             EXAMPLE_PIN_NUM_TOUCH_SDA, EXAMPLE_PIN_NUM_TOUCH_SCL, 0x5A);
    ESP_LOGI(TAG, "不使用中断引脚，采用轮询方式读取触摸数据");
    
    esp_lcd_touch_config_t tp_cfg = {
        .x_max = EXAMPLE_LCD_H_RES,
        .y_max = EXAMPLE_LCD_V_RES,
        .rst_gpio_num = EXAMPLE_PIN_NUM_TOUCH_RST,  // -1 不使用复位
        .int_gpio_num = EXAMPLE_PIN_NUM_TOUCH_INT,  // -1 不使用中断
        .levels = {
            .reset = 0,      
            .interrupt = 0,  
        },
        .flags = {
            .swap_xy = false,
            .mirror_x = false,  
            .mirror_y = false,  
        },
        .process_coordinates = NULL,  // 使用默认坐标处理
        .interrupt_callback = NULL,   // 轮询模式，无中断回调
    };
    
    ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_cst9217(tp_io_handle, &tp_cfg, &touch_handle));
    ESP_LOGI(TAG, "触摸面板创建成功");
}

/**
 * @brief 初始化QSPI总线
 */
static esp_lcd_panel_io_handle_t init_qspi_bus(void)
{
    ESP_LOGI(TAG, "初始化QSPI总线...");
    
    // 配置QSPI总线
    esp_lcd_panel_io_spi_config_t io_config = CO5300_PANEL_IO_QSPI_CONFIG(
        EXAMPLE_PIN_NUM_LCD_CS,
        NULL,  // 没有回调函数
        NULL   // 没有用户上下文
    );
    io_config.pclk_hz = AMOLED_QSPI_MAX_PCLK;
    
    spi_bus_config_t bus_config = CO5300_PANEL_BUS_QSPI_CONFIG(
        EXAMPLE_PIN_NUM_LCD_PCLK,
        EXAMPLE_PIN_NUM_LCD_DATA0,
        EXAMPLE_PIN_NUM_LCD_DATA1,
        EXAMPLE_PIN_NUM_LCD_DATA2,
        EXAMPLE_PIN_NUM_LCD_DATA3,
        EXAMPLE_LCD_H_RES * EXAMPLE_LCD_V_RES * 2  // RGB565需要2字节每像素
    );

    esp_lcd_panel_io_handle_t io_handle = NULL;
    
    // 初始化SPI总线
    ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &bus_config, SPI_DMA_CH_AUTO));
    ESP_LOGI(TAG, "QSPI总线初始化成功");
    
    // 创建面板IO句柄
    ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)SPI3_HOST, &io_config, &io_handle));
    ESP_LOGI(TAG, "面板IO创建成功");
    
    return io_handle;
}

/**
 * @brief 初始化LCD面板
 */
static void init_lcd_panel(esp_lcd_panel_io_handle_t io_handle)
{
    ESP_LOGI(TAG, "初始化CO5300面板...");
    
    esp_lcd_panel_dev_config_t panel_config = {
        .reset_gpio_num = EXAMPLE_PIN_NUM_LCD_RST,
        .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
        .bits_per_pixel = 16,  // RGB565
        .flags = {
            .reset_active_high = 0,  // 复位信号低电平有效
        },
        .vendor_config = NULL,  // 使用默认初始化序列
    };

    ESP_ERROR_CHECK(esp_lcd_new_panel_co5300(io_handle, &panel_config, &panel_handle));
    ESP_LOGI(TAG, "面板创建成功 - 使用默认初始化序列");

    // 复位面板
    ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle));
    ESP_LOGI(TAG, "面板复位完成");

    // 初始化面板
    ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle));
    ESP_LOGI(TAG, "面板初始化完成");

    // 设置间隙
    ESP_ERROR_CHECK(esp_lcd_panel_set_gap(panel_handle, EXAMPLE_LCD_X_GAP, EXAMPLE_LCD_Y_GAP));

    // 开启显示
    ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true));
    ESP_LOGI(TAG, "显示器已开启");
}

/**
 * @brief 初始化LVGL显示驱动
 */
static void init_lvgl_display(void)
{
    ESP_LOGI(TAG, "初始化LVGL...");
    
    // 初始化LVGL端口 - 防看门狗超时配置
    const lvgl_port_cfg_t lvgl_cfg = {
        .task_priority = 3,        // 适中优先级，避免阻塞其他任务
        .task_stack = 8192,        // 标准堆栈大小
        .task_affinity = -1,       // 任意核心运行
        .task_max_sleep_ms = 100,  // 适当休眠，避免过度占用CPU
        .timer_period_ms = 50,     // 50FPS，平衡性能和稳定性
    };
    ESP_ERROR_CHECK(lvgl_port_init(&lvgl_cfg));
    ESP_LOGI(TAG, "LVGL端口初始化成功 - 性能优化配置");

    // 创建显示端口配置 - AMOLED偶数对齐优化
    const lvgl_port_display_cfg_t disp_cfg = {
        .io_handle = panel_io_handle,            // 必需的IO句柄
        .panel_handle = panel_handle,            // 面板句柄
        .buffer_size = EXAMPLE_LCD_H_RES * 50,   // 50行缓冲区，确保偶数对齐
        .double_buffer = true,                   // 启用双缓冲，减少撕裂
        .hres = EXAMPLE_LCD_H_RES,
        .vres = EXAMPLE_LCD_V_RES,
        .monochrome = false,
        .color_format = LV_COLOR_FORMAT_RGB565,
        .rotation = {
            .swap_xy = false,     // CO5300不支持swap_xy
            .mirror_x = false,
            .mirror_y = false,
        },
        .flags = {
            .buff_dma = false,    // PSRAM不兼容DMA
            .buff_spiram = true,  // 使用PSRAM缓冲区
            .swap_bytes = true,   // 交换RGB565字节序
            .full_refresh = false,// 增量刷新，避免看门狗超时
            .direct_mode = false, // 不使用直接模式
        }
    };

    // 添加显示器到LVGL
    lvgl_disp = lvgl_port_add_disp(&disp_cfg);
    if (lvgl_disp == NULL) {
        ESP_LOGE(TAG, "LVGL显示器创建失败");
        return;
    }
    
    // 配置AMOLED屏幕偶数对齐优化
    configure_amoled_alignment();
    
    // 设置AMOLED屏幕偶数对齐rounder回调函数 - 解决撕裂问题
    // 在LVGL 9.x中，通过事件系统实现rounder功能
    lv_display_add_event_cb(lvgl_disp, amoled_rounder_event_cb, LV_EVENT_INVALIDATE_AREA, NULL);
    
    ESP_LOGI(TAG, "CO5300 AMOLED偶数对齐rounder事件回调已设置");
    
    ESP_LOGI(TAG, "LVGL显示器创建成功");
    ESP_LOGI(TAG, "CO5300 AMOLED偶数对齐rounder回调已设置 - 防止屏幕撕裂");
    ESP_LOGI(TAG, "显示缓冲区大小: %d 像素 (偶数对齐优化)", EXAMPLE_LCD_H_RES * 50);
    ESP_LOGI(TAG, "颜色格式: RGB565 (2字节对齐)");
    ESP_LOGI(TAG, "双缓冲: 启用 (防撕裂)");
    ESP_LOGI(TAG, "字节交换: 启用");
    ESP_LOGI(TAG, "PSRAM缓冲: 启用");
    ESP_LOGI(TAG, "增量刷新: 启用 (防超时)");
}

/**
 * @brief 初始化LVGL触摸输入 - 轮询方式
 */
static void init_lvgl_touch(void)
{
    ESP_LOGI(TAG, "初始化LVGL触摸输入...");
    
    // 创建触摸输入设备配置
    const lvgl_port_touch_cfg_t touch_cfg = {
        .disp = lvgl_disp,
        .handle = touch_handle,
    };
    
    // 添加触摸输入设备到LVGL
    lvgl_touch_indev = lvgl_port_add_touch(&touch_cfg);
    if (lvgl_touch_indev == NULL) {
        ESP_LOGE(TAG, "LVGL触摸输入创建失败");
        return;
    }
    
    ESP_LOGI(TAG, "LVGL触摸输入创建成功");
    ESP_LOGI(TAG, "触摸分辨率: %dx%d", EXAMPLE_LCD_H_RES, EXAMPLE_LCD_V_RES);
    ESP_LOGI(TAG, "使用ESP-LCD-Touch驱动轮询方式");
}

/**
 * @brief 运行LVGL演示
 */
static void run_lvgl_demo(void)
{
    ESP_LOGI(TAG, "启动LVGL Widgets演示...");
    
    // 锁定LVGL
    lvgl_port_lock(0);
    
    // 运行widgets演示
    lv_demo_widgets();
    
    // 解锁LVGL
    lvgl_port_unlock();
    
    ESP_LOGI(TAG, "LVGL Widgets演示已启动");
}

/**
 * @brief LVGL任务
 */
static void lvgl_demo_task(void *pvParameters)
{
    ESP_LOGI(TAG, "LVGL演示任务启动");
    
    // 等待一段时间确保初始化完成
    vTaskDelay(pdMS_TO_TICKS(200));
    
    // 运行支持触摸交互的演示
    ESP_LOGI(TAG, "启动带触摸交互的Widgets演示...");
    run_lvgl_demo();
    
    // 保持任务运行
    while (1) {
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

void app_main(void)
{
    ESP_LOGI(TAG, "CO5300 AMOLED + LVGL + 触摸演示开始");
    ESP_LOGI(TAG, "屏幕分辨率: %dx%d", EXAMPLE_LCD_H_RES, EXAMPLE_LCD_V_RES);
    ESP_LOGI(TAG, "QSPI最大时钟: %d MHz", AMOLED_QSPI_MAX_PCLK / 1000000);
    ESP_LOGI(TAG, "LVGL版本: %d.%d.%d", lv_version_major(), lv_version_minor(), lv_version_patch());
    
    // AMOLED屏幕确认
    init_backlight();
    
    // 初始化QSPI总线
    panel_io_handle = init_qspi_bus();
    
    // 初始化LCD面板
    init_lcd_panel(panel_io_handle);
    
    // 初始化触摸I2C总线
    esp_lcd_panel_io_handle_t touch_io_handle = init_touch_i2c();
    
    // 初始化触摸面板
    init_touch_panel(touch_io_handle);
    
    // 初始化LVGL显示
    init_lvgl_display();
    
    // 初始化LVGL触摸 (仅在显示器成功创建时)
    if (lvgl_disp != NULL) {
        init_lvgl_touch();
    } else {
        ESP_LOGE(TAG, "跳过触摸初始化，显示器创建失败");
        return;
    }
    
    ESP_LOGI(TAG, "所有初始化完成，启动LVGL演示...");
    
    // 延迟启动演示，让系统稳定
    vTaskDelay(pdMS_TO_TICKS(200));
    
    // 创建LVGL演示任务
    xTaskCreate(lvgl_demo_task, "lvgl_demo_task", LVGL_TASK_STACK_SIZE, NULL, LVGL_TASK_PRIORITY, NULL);
    
    ESP_LOGI(TAG, "LVGL演示任务已创建，支持触摸交互");
}